/*
 *  Copyright 1999-2019 Seata.io Group.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.auditlog.datasource;

import com.auditlog.datasource.context.ContextHolder;
import com.auditlog.listener.EventPublisher;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;

/**
 * The type Connection proxy.
 *
 * @author sharajava
 */
public class ConnectionProxy extends AbstractConnectionProxy {

    public ConnectionProxy(DataSourceProxy dataSourceProxy, Connection targetConnection) {
        super(dataSourceProxy, targetConnection);
    }


    @Override
    public void commit() throws SQLException {
        doCommit();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        Savepoint savepoint = targetConnection.setSavepoint();
        return savepoint;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        Savepoint savepoint = targetConnection.setSavepoint(name);
        return savepoint;
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        targetConnection.rollback(savepoint);
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        targetConnection.releaseSavepoint(savepoint);
    }


    private void doCommit() throws SQLException {
        try {
            targetConnection.commit();
        } finally {
            if (ContextHolder.getExecuteContext().getExecutedRecordImages().size() > 0) {
                EventPublisher.publishRecordChangeEvent();
            }
            ContextHolder.reset();
        }
    }

    @Override
    public void rollback() throws SQLException {
        try {
            targetConnection.rollback();
        } finally {
            ContextHolder.reset();
        }
    }

    /**
     * change connection autoCommit to false by seata
     *
     * @throws SQLException the sql exception
     */
    public void changeAutoCommit() throws SQLException {
        setAutoCommit(false);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        if (autoCommit && !getAutoCommit()) {
            // change autocommit from false to true, we should commit() first according to JDBC spec.
            doCommit();
        }
        targetConnection.setAutoCommit(autoCommit);
    }
}
